/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "S_Object.h"
#include "core/动画/an_曲线.h"
#include <线性代数/变换.h>

#include "底层绘图/底层绘图框架.h"


/*
* 
* 骨骼
*	|____
* 物体	|
*	|__网格
*/



#define DEF_物体动画曲线(c) ((S_动画曲线组*)c->ptr_userData)

#define DEF_骨骼朝向 (vec3{ 0, 0, 1 })



struct S_物体变换 : public S_Object {
	Mat44f		m_矩阵;
	S_Tranform	m_变换;
	//__m512		m_Mat;

	void		f_set矩阵(const float32* mat);
};


typedef struct {
	int32 是否独立缩放;
	float32 Z缩放;
	float32 Z偏移;
	float32 Z;
}S_单色材质属性;



class C_骨骼管理 {
public:
	static std::set<S_骨架*> m_骨骼容器;
	C_骨骼管理();
	~C_骨骼管理();
};









#define DEF_物体动画曲线组	S_List*
#define DEF_物体骨骼Prt		S_Tree*
#define DEF_骨骼组(b)		((S_Tree*)(b))
#define DEF_骨骼(b)			((S_骨架*)((b)->ptr_userData))



typedef void(*fp_物体数据更新函数)(void* data);


struct S_物体 : public S_Object {
	//S_设备环境  m_Ctx;
	S_Tranform	m_变换;
	E_物体类型  m_Type;
	uint32      m_实例ID;
	//uint32      m_实例数量;
	uint32      m_变换ID;


	void*		m_UserData;
	void**		m_Data;
	//S_物理体*	m_物理体;
	bool		m_是否实例;
	bool		m_根实例;
	bool		m_可拾取;

	std::vector<S_物体*>	m_子物体;
	S_物体*					m_父物体;

	S_GPU内存块索引 m_变换矩阵;
	S_GPU内存块索引 m_物体属性;
	S_GPU内存块索引 m_光追实例加速结构;

	std::vector<S_GPU内存块索引> m_实例颜色;
	

	//同时控制深度控制
	S_板载缓存*	m_独立缩放;
	//S_板载缓存* m_间接;
	S_VkDrawIndirectCommand        m_PickIndirect;
	S_VkDrawIndexedIndirectCommand m_IndexeIndirect;
	//S_GPU参数布局*	m_GPU参数布局;
	

	//DEF_物体动画曲线组	m_动画曲线;
	S_曲线通道*	m_位置;
	S_曲线通道*	m_旋转;
	S_曲线通道*	m_缩放;
	float32		m_TimeOffset;
	//S_物体*			m_骨骼;
	S_骨架*		m_骨架;
	S_Cube		m_包围盒;
	S_Bounding  m_Bound;
	S_GPU内存块索引 m_包围盒_GpuMem;

	

	uint16		m_DataNum;
	bool		m_isUpdate;
	bool		m_isUpdateMatrix;
	bool		m_UpdateGPU参数布局;

	bool		m_渲染;
	bool		m_销毁;
	
	


	static float64 g_前一帧;
	static float64 g_当前帧;
	static bool		   g_更新曲线关键帧;

	//================= 向全局内存分配过渡 =====================
	static S_板载缓存*				g_变换矩阵;
	static S_板载缓存*				g_物体属性;
	static std::vector<S_板载缓存*> g_物体颜色;

	static S_板载缓存* g_骨骼长度;
	static S_板载缓存* g_姿态变换;
	static S_板载缓存* g_骨骼变换;


	static S_物体*     g_包围盒物体;



	S_物体(E_物体类型 type, uint32 id_name=0);
	~S_物体();

	//S_Object*	f_get(uint32 key);
	//S_Object*	f_get子类对象(uint32 key);
	void		f_set位置(float32 x, float32 y, float32 z);
	void		f_set旋转(float32 x, float32 y, float32 z);
	void		f_set缩放(float32 x, float32 y, float32 z);
	void		f_set位置(const vec3& xyz) { m_变换.location = xyz; m_isUpdate = true;}
	void		f_set旋转(const vec3& xyz) { m_变换.rotation = xyz; m_isUpdate = true;}
	void		f_set缩放(const vec3& xyz) { m_变换.scale = xyz; m_isUpdate = true;}

	void		f_set位置(const vec3& xyz, uint32 实例);
	void		f_set旋转(const vec3& xyz, uint32 实例);
	void		f_set缩放(const vec3& xyz, uint32 实例);

	vec3		f_get位置();
	vec3		f_get旋转();
	vec3		f_get缩放();
	vec4		f_get四元数();
	//std::vector<C_Mat44>	f_get矩阵(uint32 ID);
	std::vector<Mat44f>		f_get矩阵2(uint32 ID);
	C_Mat44		f_get矩阵() const;
	Mat44f		f_get矩阵2() const;

	virtual		void		f_set矩阵(const Mat44f* mat);
	virtual		void		f_set矩阵(const Mat44f* mat, uint32);
	virtual		void		f_set矩阵mt(const Mat44f* mat) {}
	
	virtual		void		f_set变换(const void* mat, uint32 id) {}
	
	void		f_setData(void* data, uint16 loc = 0);
	void		f_setDataNum(uint16 num);
	//virtual		void		f_updateGPU参数布局() {}
	virtual		std::vector<S_物体*>	f_创建实例(uint32 num);
	

	void		f_set碰撞类型();
	void		f_set碰撞形状();


	//virtual		void		f_Update(S_Object* 摄像机);
	virtual		void		f_Update(Mat44f* c, Mat44f* 父级变换);
	virtual		void		f_绘制(S_渲染参数& 摄像机);


	void f_打开可视通道(uint8 通道);
	void f_关闭可视通道(uint8 通道);
	void f_构建底层加速结构();

};






typedef struct {
	S_光追后端*			m_光追后端;
	S_物体*				m_灯光;
	fp_物体数据更新函数	mf_Update;
}S_灯光场景数据;






struct S_GL立即模式 : public S_物体 {
	//S_MeshBuf	m_Data;
	S_GL立即模式(S_设备环境& ctx);


	void glBegin(E_填充模式 模式);
	void glEnd();

	void glVertex(const vec3& v);
	void glColor(const S_RGBA8UI& c);
	void glNormal(const vec3& n);
	void glCoord(const vec2& t);

	void glMatrixPush();
	void glMatrixPop();
	void glClear();


	void f_绘制(S_渲染参数& 渲染参数);

private:
	uint32		m_Mask;
	uint32		m_Count;
	S_设备环境& m_Ctx;

	S_物体*		m_当前物体;

	std::vector<S_物体*> m_Data;
};





S_物体* f_get物体(uint32 id_name);

S_Mesh* f_ob_fromMesh(const S_物体* froObj, uint32 loc = 0);


void f_Ob_打开可视通道(uint8 通道);
void f_Ob_关闭可视通道(uint8 通道);



//void    f_ob_initGPU变换矩阵(S_设备环境& ctx);
void	f_ob_创建矩阵(S_物体* ob, S_设备环境& ctx, uint32 num = 1);
void	f_ob_添加矩阵(S_物体* ob, uint32 loc = -1);
void	f_ob_删除矩阵(S_物体* ob, uint32 loc = -1, uint32 num = 0);
void	f_ob_清除矩阵(S_物体* ob, uint32 num=1);
S_物体* f_ob_创建网格物体(S_设备环境 ctx);
//void	f_ob_链接骨骼(S_设备环境 ctx, S_物体* ob, S_物体* 骨骼虚拟物体);
S_骨骼* f_ob_get骨骼数据(S_物体* ob, uint8 loc = 0);
Mat44f		f_ob_get实例变换矩阵(S_物体* Obj, uint32 ID);
//Mat44f		f_ob_get父对象变换矩阵(S_物体* Obj, uint32 ID, uint32 depth = 0, bool 包含顶层 = false);
Mat44f f_ob_get父对象变换矩阵(S_物体* Obj, uint32 depth, bool 包含顶层 = false);


//float64*	f_ob_get全局时间帧();
void		f_ob_步进时间帧(float32 f);
void		f_ob_set步进时间帧(float64 f);
//void		f_ob_填充间接绘制(S_物体* ob, const std::vector<S_VkDrawIndirectCommand>& indirect);
//void		f_ob_填充间接绘制(S_物体* ob, const std::vector<S_VkDrawIndexedIndirectCommand>& indirect);

//Mat44f		f_ob_构建XYZ变换矩阵(const S_物体* ob);
Mat44f		f_ob_构建XYZ变换矩阵euler(const S_物体* ob);
Mat44f		f_ob_构建XYZ变换矩阵euler(const vec3& rot);


S_骨骼IK*	f_ob_创建IK();
void		f_ob_销毁IK(S_骨骼IK* ik);
S_骨骼IK**	f_ob_添加IK(S_骨架* 骨骼, uint16 IK数量);

S_骨架*		f_ob_创建骨架();
S_骨架*		f_ob_from骨架(const S_物体* froObj, uint32 loc = 0);

//void		f_ob_计算骨骼变换(S_物体* ob);
vec3		f_ob_计算骨骼IK中点(S_骨骼IK* IK);
vec3		f_ob_计算骨骼IK点(S_物体* ob, bool 尾部);
vec4		f_ob_计算IK旋转向量(S_骨骼IK* IK);
void		f_ob_更新骨骼IK(S_物体* ob, S_骨架* 骨架, Mat44f* 骨骼物体变换矩阵, const Mat44f& 父级变换);
void		f_ob_解算IK骨骼(S_骨骼IK* ik, Mat44f* 骨骼物体变换矩阵, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换);
void		f_ob_解算IK骨骼IK步进坐标(S_骨骼IK* ik, vec3* 骨节, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换);
void		f_ob_从骨节更新编辑骨骼(
										S_物体* 根骨骼, 
										vec3* 骨节, 
										const float32* 骨骼长度, 
										Mat44f* 骨骼物体变换矩阵, 
										const vec4& 父骨骼旋转, 
										const Mat44f& 父矩阵, 
										const vec3& s, 
										float32 l
									);




void		f_ob_ge骨节坐标(S_物体* 根骨骼, vec3* 骨节, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换);

void		f_ob_构建骨骼变换GPU数据(S_骨架* 骨架, const Mat44f* 骨骼变换矩阵);

Inline void f_mesh_set物体属性(S_物体* ob, const S_MeshTranformProp& prop, uint32 offset) {
	f_buf_物体变换属性_at(ob->m_物体属性, offset) = prop;
}













